//
//  MPCImageView.m
//  Pods
//
//  Created by 蔡勋 on 2017/7/15.
//
//

#import "MPCImageView.h"
#import "MPCImageView+SDWebImage.h"
#import "MPCImageView+YYWebImage.h"
#import <pthread.h>
#import "NSString+Tools.h"
#import "NSURL+Tools.h"
#import "objc/runtime.h"


@implementation MPCImageViewBtn


@end


@interface MPCImageView ()

// 为imageView添加一个button，实现点击事件
@property (nonatomic, strong) MPCImageViewBtn *btn;


@end


@implementation MPCImageView


#pragma mark - *********************************** View Lifecycle **********************************

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        /// 初始化变量
        [self initVariable];
        
        /// 设置公共属性，与App的UI规范 无关
        [self setCommonAttribute];
        
        /// 设置公共属性，与App的UI规范 有关
        [self setCustomAttribute];
    }
    
    return self;
}

- (void)initVariable
{
    _fltAnimDuration = 0.2;
}

/// 设置公共属性，与App的UI规范 无关
- (void)setCommonAttribute
{
    if (self)
    {
        self.backgroundColor = [UIColor clearColor];
        
        self.clipsToBounds = YES;
    }
}

/// 设置公共属性，与App的UI规范 有关
- (void)setCustomAttribute
{
    if (self)
    {
        /// 下载完成后默认显示模式为拉伸放大
        _commonContentMode = UIViewContentModeScaleAspectFit;
        _placeholderImgContentMode = UIViewContentModeCenter;
        self.contentMode = _commonContentMode;
        
        _imgPlaceholder = [UIImage imageNamed:@""];
        
        /// 默认显示占位图片
        _isShowPlaceholderImg = YES;
        _isShowDismissAnimated = YES;
    }
}

- (void)dealloc
{
    
}


#pragma mark - ********************************** 初始化方法 工厂模式 *********************************

+ (instancetype)getWithFrame:(CGRect)frame
{
    MPCImageView *imgv = [[self alloc] initWithFrame:frame];
    
    return imgv;
}

+ (instancetype)getWithFrame:(CGRect)frame image:(UIImage *)img
{
    MPCImageView *imgv = [[self alloc] initWithFrame:frame image:img];
    
    return imgv;
}


#pragma mark - ********************************** 初始化方法 实例方法 *********************************

- (instancetype)initWithFrame:(CGRect)frame image:(UIImage *)img
{
    if (self = [self initWithFrame:frame])
    {
        [self setImage:img];
    }
    
    return self;
}

/// 添加一个点击事件
- (void)addTarget:(id)target action:(SEL)selAction
{
    if (self)
    {
        /// 打开UI交互
        self.userInteractionEnabled = YES;
        
        if (!_btn)
        {
            ///  添加一个透明的control，实现点击事件
            _btn = [[MPCImageViewBtn alloc] initWithFrame:self.bounds];
            _btn.backgroundColor = [UIColor clearColor];
            [_btn addTarget:target
                     action:selAction
           forControlEvents:UIControlEventTouchUpInside];
            _btn.imgv = self;
            [self addSubview:_btn];
        }
    }
}

- (MPCImageView * _Nullable (^_Nullable)(BOOL))showDismissAnimated
{
    return ^MPCImageView *(BOOL showDismissAnimated)
    {
        _isShowDismissAnimated = showDismissAnimated;
        
        return self;
    };
}

- (MPCImageView * _Nullable (^_Nullable)(CGFloat))animDuration
{
    return ^MPCImageView *(CGFloat animDuration)
    {
        _fltAnimDuration = animDuration;
        
        return self;
    };
}

- (MPCImageView * _Nullable (^_Nullable)(UIImage *_Nullable))imagePlaceholder
{
    return ^MPCImageView *(UIImage *imagePlaceholder)
    {
        _imgPlaceholder = imagePlaceholder;
        
        return self;
    };
}

- (MPCImageView * _Nullable (^_Nullable)(UIImage *_Nullable))imageError
{
    return ^MPCImageView *(UIImage *imageError)
    {
        _imgError = imageError;
        
        return self;
    };
}

- (MPCImageView * _Nullable (^_Nullable)(BOOL))showPlaceholderImg
{
    return ^MPCImageView *(BOOL showPlaceholderImg)
    {
        _isShowPlaceholderImg = showPlaceholderImg;
        
        return self;
    };
}

- (MPCImageView * _Nullable (^_Nullable)(BOOL))placeholderImageContentMode
{
    return ^MPCImageView *(BOOL placeholderImageContentMode)
    {
        _placeholderImgContentMode = placeholderImageContentMode;
        
        return self;
    };
}

- (MPCImageView * _Nullable (^_Nullable)(BOOL))selfCommonContentMode
{
    return ^MPCImageView *(BOOL selfCommonContentMode)
    {
        _commonContentMode = selfCommonContentMode;
        self.contentMode = selfCommonContentMode;
        
        return self;
    };
}

#pragma mark - *********************************** 设置属性 实例方法 **********************************

/// 设置圆角、边框
- (void)setCornerRadius:(CGFloat)fltCornerRadius
            borderWidth:(CGFloat)fltBorderWidth
            borderColor:(UIColor *)colorBorder
{
    if (self)
    {
        self.layer.cornerRadius = fltCornerRadius;
        self.layer.borderColor = colorBorder.CGColor;
        
        /// 根据屏幕的分辨率倍数适配边框宽度
        self.layer.borderWidth = [self scaleAdaptWidth:fltBorderWidth];
    }
}

- (void)setCornerRadiusForAll:(float)cornerRadius
{
    self.clipsToBounds = YES;
    self.layer.cornerRadius = cornerRadius;
}

- (void)setCornerRadiusForPart:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii
{
    // 上面两个圆角
    UIBezierPath *maskPath=  [UIBezierPath bezierPathWithRoundedRect:self.bounds
                                                   byRoundingCorners:corners
                                                         cornerRadii:cornerRadii];
    
    CAShapeLayer *maskLayer=[[CAShapeLayer alloc] init];
    
    maskLayer.frame=self.bounds;
    
    maskLayer.path=maskPath.CGPath;
    
    self.layer.mask=maskLayer;
    
    self.layer.masksToBounds=YES;
}


/**
 网络图片加载的方法
 
 */
- (void)mp_setImageWithURL:(nullable NSString *)imageStrURL
{
    [self mp_setImageWithURL:imageStrURL options:0 progress:nil success:nil fail:nil];
}

- (void)mp_setImageWithURL:(nullable NSString *)imageStrURL options:(MPWebImageOptions)options
{
    [self mp_setImageWithURL:imageStrURL options:options progress:nil success:nil fail:nil];
}

- (void)mp_setImageWithURL:(nullable NSString *)imageStrURL
                   options:(MPWebImageOptions)options
                   success:(nullable MPWebImageSuccessBlock)success
                      fail:(nullable MPWebImageFailBlock)fail
{
    [self mp_setImageWithURL:imageStrURL options:options progress:nil success:success fail:fail];
}


- (void)mp_setImageWithURL:(nullable NSString *)imageStrURL
                   options:(MPWebImageOptions)options
                  progress:(nullable MPWebImageDownloaderProgressBlock)progressBlock
                   success:(nullable MPWebImageSuccessBlock)success
                      fail:(nullable MPWebImageFailBlock)fail
{
    
    /// 检查URL是否合理
    NSURL *imageURL = [self changeImageUrl:imageStrURL];
    if (MPT_URL_Not_Valid(imageURL))
    {
        return;
    }
    
    /// 移除之前下载队列
    [self mp_cancelCurrentImageLoadWithURL:imageURL];
    [self.layer removeAnimationForKey:MPWebImageFadeAnimationKey];

    /// 设置默认图片  如果用户没有设置自动填充图片模式
    [self mp_setPlaceholderWithOptions:options];

    /// 读取缓存中的图片
   UIImage *imageMemory = [self mp_getCatcheMemoryImageWithImageURL:imageURL options:options];
    
    if (imageMemory)
    {
        if (success)
        {
            success(imageMemory,imageURL,MPWebImageFromType_Memory,MPWebImageStage_Finished);
        }
        
        return;
    }
    
   /// 读取硬盘中的图片
     [self mp_getCatcheDiskImageWithImageURL:imageURL options:options finish:^(UIImage *image)
    {
        /// 硬盘中有图片
        if (image)
        {
            if (success)
            {
                success(image,imageURL,MPWebImageFromType_Disk,MPWebImageStage_Finished);
            }
        }
        /// 硬盘中无图片，需要下载
        else
        {
            /// 下载网络图片
            [self mp_downImageWithImageURL:imageURL options:options progress:progressBlock success:success fail:fail];
        }
        
    }];
}

#pragma mark - ************************************* Functions *************************************

/// 是否显示图片（有图模式）
- (BOOL)shouldShowImage
{
    // 先写死，日后如果有需求的话弄个成员变量去控制
    return YES;
}

- (BOOL)tpCheckImageURL:(NSString *)strImgUrl
{
    if (!([strImgUrl hasPrefix:@"http:"] || [strImgUrl hasPrefix:@"https:"])) /// 不是URL,直接返回NO
    {
        return NO;
    }
    
    /// 对URL转码，处理URL中有汉字的情况
    NSString *strCode = [strImgUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    /// 获取img的URL
    NSURL *urlImg = [NSURL URLWithString:strCode];
    
    /// 根据urlImg的path是否为空来判断是否为图片地址
    return MPT_Str_Is_Valid([urlImg path]);
}

- (CGFloat)scaleAdaptWidth:(CGFloat)fltWidth
{
    /// 如果宽度为0，则直接返回
    if (fltWidth == 0)
    {
        return fltWidth;
    }
    
    /// 获取屏幕的像素密度，如iPhone6Plus，一个点上有3个像素，该值为3
    CGFloat fltScale = [UIScreen mainScreen].scale;
    /// 传入的参数最小值要求为1，如果小于1，则设为1，保证像素最小值为1
    if (fltWidth < 1.0)
    {
        fltWidth = 1.0;
    }
    /// 要显示的点除以屏幕密度，为要返回的点，比实际传进来的要小
    return (fltScale > 0 ? (fltWidth / fltScale) : fltWidth);
}

- (NSURL *)changeImageUrl:(NSString *)strImgUrl
{
    /// 无图片模式，直接返回
    if (![self shouldShowImage])
    {
        return nil;
    }
    
    /// 图片连接是为空，直接返回
    if (MPT_Str_Not_Valid(strImgUrl))
    {
        return nil;
    }
    
    /// 图片链接是否正常
    if (![self tpCheckImageURL:strImgUrl])
    {
        return nil;
    }
    
    /// 对URL转码，处理URL中有汉字的情况
    strImgUrl = [strImgUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    /// 获取img的URL
    NSURL *urlImg = [NSURL URLWithString:strImgUrl];
    
    return urlImg;
}

/// 淡入动画，从无到有
- (void)animationEaseIn:(UIView *)view
{
    CATransition *transition = [CATransition animation];
    transition.duration = _fltAnimDuration>0?_fltAnimDuration:0.2;
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.type = kCATransitionFade;
    [self.layer addAnimation:transition forKey:MPWebImageFadeAnimationKey];
}

- (void)noFinishWhitImage:(UIImage *)image
{
    self.image = image;
    self.contentMode = _commonContentMode;
    
    [self setNeedsLayout];
}

- (void)didFinishWithImage:(UIImage*)image
{
    /// 加入一个保护，判断是否下载完成成功
    if ((![image isKindOfClass:[UIImage class]])
        || (image.size.height <= 0))
    {
        return;
    }
    
    /// 下载图片成功，显示图片
    [self setImage:image];
    /// 下载成功后，设置显示模式，此时使用的是调用commonContentMode:方法设置的值，在外面手动调用系统方法是不起作用的
    self.contentMode = _commonContentMode;
    
    ///  是否显示消失动画
    if (self.isShowDismissAnimated)
    {
        [self animationEaseIn:self];
    }
}

- (void)didFailWithError:(NSError *)error
{
#ifdef DEBUG /// 测试模式下
    if (error.code == 404) /// 如果是404则显示提示404错误图片
    {
#warning 这块需要替换真正的404错误图片
        [self setImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"" ofType:@"jpg"]]];
    }
#endif
    
    if (!_imgError || ![_imgError isKindOfClass:[UIImage class]])
    {
        self.image = self.imgPlaceholder;
        
        return;
    }
    
    /// 设置错误图片
    [self setImage:_imgError];
    
    ///  是否显示消失动画
    if (self.isShowDismissAnimated)
    {
        [self animationEaseIn:self];
    }
    
}


#pragma mark -- 需要区分SDK的部分

+ (dispatch_queue_t)mp_setterQueue
{
    static dispatch_queue_t queue;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        queue = dispatch_queue_create("com.yixia.mpwebimage.setter", DISPATCH_QUEUE_SERIAL);
        dispatch_set_target_queue(queue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
    });
    return queue;
}

- (void)mp_cancelCurrentImageLoadWithURL:(NSURL *)url
{
#if MPT_USE_SDWebImageSwitch

    [self sd_cancelImageLoadOperationWithKey:@"UIImageViewAnimationImages"];
#else
    [self yy_cancelCurrentImageLoadWithURL:url];

#endif

}



- (void)mp_setPlaceholderWithOptions:(MPWebImageOptions)options
{
    mp_dispatch_main_sync_safe(^{
        
        if (options & MPWebImageOption_IgnorePlaceHolder)
        {
            return;
        }
        
        /// 下载之前显示占位图片
        if (_isShowPlaceholderImg)
        {
            [self setImage:_imgPlaceholder];
            
            /// 设置占位图片的显示模式，使占位图片不拉伸比例居中显示
            self.contentMode = _placeholderImgContentMode;
        }

    });
}

- (UIImage *)mp_getCatcheMemoryImageWithImageURL:(NSURL *)imgUrl options:(MPWebImageOptions)options
{
#if MPT_USE_SDWebImageSwitch
    return [self sd_getCatcheMemoryImageWithImageURL:imgUrl options:options];

#else
    
    return [self yy_getCatcheMemoryImageWithImageURL:imgUrl options:options];

#endif

}

- (void)mp_getCatcheDiskImageWithImageURL:(NSURL *)imgUrl options:(MPWebImageOptions)options finish:(void (^)(UIImage *image))finish
{
#if MPT_USE_SDWebImageSwitch

    [self sd_getCatcheDiskImageWithImageURL:imgUrl options:options finish:finish];
#else
    [self yy_getCatcheDiskImageWithImageURL:imgUrl options:options finish:finish];

#endif

}

- (void)mp_downImageWithImageURL:(NSURL *)imgUrl
                         options:(MPWebImageOptions)options
                        progress:(MPWebImageDownloaderProgressBlock)progressBlock
                         success:(nullable MPWebImageSuccessBlock)success
                            fail:(nullable MPWebImageFailBlock)fail
{
    
#if MPT_USE_SDWebImageSwitch
    
    [self sd_downImageWithImageURL:imgUrl
                           options:options
                          progress:progressBlock
                           success:success
                              fail:fail];
#else
    [self yy_downImageWithImageURL:imgUrl
                           options:options
                          progress:progressBlock
                           success:success
                              fail:fail];
#endif
    
}


@end


